/**
 * Nettle main code
 * (C) Nettle developers 2000-2001
 *
 * $Id: main,v 1.45 2002/02/10 03:12:59 ijeffray Exp $
 */

#include "generic.h"
#include "globals.h"

#include "init.h"
#include "main.h"
#include "misc.h"
#include "quit.h"
#include "sockwatch.h"
#include "url.h"
#include "wimp.h"



bool main_requirenull = false; /* this is set to true if anything decides it
                                 * needs null polls. (eg. sockets with more
                                 * data waiting than they want to handle
                                 * and during dns / connect, etc.) */

const char *__dynamic_da_name = "Nettle Heap";


int main(int argc, char *argv[])
{
  int i;
  enum { s_none, s_url } state;

  initialise_application();

  state = s_none;
  for (i = 1; i < argc; i++)
  {
    switch (state)
    {
      case s_none:
        if (strcmp(argv[i], "-url") == 0)
          state = s_url;
        break;

      case s_url:
        wimp_handleurl(argv[i], 0);
        break;

      default:
        assert(0);
    }
  }

  while (!quit_flag)
  {
    union wimp_poll_block wimp_block;
    int event;
    int nextpolltime;
    int mask = (1<<4)  | /* pointer enter window */
               (1<<5)  | /* pointer leave window */
               0;

    if (socketwatch_pollword != NULL)
    {
      mask |= (1<<22); /* R3 is pointer to pollword */
      /* FIXME: need to set nextpolltime shorter if dns or connect in
       * progress (and selection too?) */
      nextpolltime = _swi(OS_ReadMonotonicTime, _RETURN(0));
      if (main_requirenull)
        nextpolltime += 0; /* immediate null required */
      else if (selection_in_progress)
        nextpolltime += 5; /* reasonable number of updates required to redraw
                            * selection as mouse moves */
      else if (resize_handle)
        nextpolltime += min(CURSOR_BLINK_DELAY,10);
      else if (((cursor_blink || !cursor_state) && cursor_session) || (blinking && want_blink) )
      {
        if (nextcursortime - nextpolltime < 0)
          nextpolltime += CURSOR_BLINK_DELAY;
        else
          nextpolltime = nextcursortime;
      }
      else
        nextpolltime += 500; /* otherwise, wait 5 seconds between nulls */
    }
    else
    {
      nextpolltime = _swi(OS_ReadMonotonicTime, _RETURN(0)) + 5;
    }

    /* Provide a suitable default in case DeepKeys isn't available */
    wimp_block.key_pressed.extra = 0;

    event = _swi(Wimp_PollIdle, _INR(0,3) | _RETURN(0),
                 mask, &wimp_block, nextpolltime, socketwatch_pollword);

    switch (event)
    {
      case 0:
        /* null reason code */
        main_requirenull = false;
        wimp_nullreasoncode();
        break;
      case 1:
        /* redraw request */
        redraw_window(&wimp_block);
        break;
      case 2:
        /* open window request - call with window handle and whether this */
        /* is a wimp poll or not */
        open_window((struct wimp_openwindow_block*)&wimp_block, wimp_block.open_window.window_handle);
        break;
      case 3:
        /* close window request - call with window handle  */
        close_window(wimp_block.close_window.window_handle);
        break;
      case 6:
        /* mouse click request, call with x, y, buttons, window handle and icon_handle */
        wimp_mouse_click(wimp_block.mouse_click.pos.x,
                         wimp_block.mouse_click.pos.y,
                         wimp_block.mouse_click.buttons,
                         wimp_block.mouse_click.window_handle,
                         wimp_block.mouse_click.icon_handle);
        break;
      case 7:
        /* drag finished */
        drag_finished();
        break;
      case 8:
        /* key press, call with window handle, icon handle and key */
        key_pressed(wimp_block.key_pressed.window_handle,
                    wimp_block.key_pressed.icon_handle,
                    wimp_block.key_pressed.code,
                    wimp_block.key_pressed.extra);
        /* check the sockets for data, in case someone is holding down a key
         * and we're not getting null events. */
        wimp_nullreasoncode();
        break;
      case 9:
        /* menu selection */
        wimp_menu_selection(wimp_block.menu_selection.menu);
        break;
      case 11:
        /* lose caret */
        lose_caret(wimp_block.caret.window_handle);
        break;
      case 12:
        /* gain caret */
        gain_caret(wimp_block.caret.window_handle);
        break;
      case 13:
        /* pollword non-zero - ie. data on a socket */
        wimp_nullreasoncode();
        break;
      case 17:
      case 18:
        /* wimp message */
        wimp_message(&wimp_block);
        break;
      case 19:
        /* wimp message bounce/ack */
        wimp_message_ack(&wimp_block);
        break;
    }
  }

  /* close down application */
  closedown_application();

  return 0;
}
